package com.jy.common.tool;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.UUID;
import javax.imageio.ImageIO;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.jy.entity.Alioss;
import com.jy.mapper.AliossMapper;

public class VideoCoverExtractor {

    private static AliossMapper aliossMapper = null;

    public VideoCoverExtractor(AliossMapper aliossMapper) {
        VideoCoverExtractor.aliossMapper = aliossMapper;
    }

    public static String saveVideoCoverToOSSAndGetUrl(String videoUrl, String aliossPosition) throws IOException {
        Alioss alioss = getAliossConfig();
        try (InputStream videoInputStream = getVideoInputStream(videoUrl);
             FFmpegFrameGrabber ff = new FFmpegFrameGrabber(videoInputStream)) {
            ff.start();
            return extractAndUploadCover(ff, alioss, aliossPosition);
        }
    }

    private static Alioss getAliossConfig() {
        return aliossMapper.selectList(null).get(0);
    }

    private static InputStream getVideoInputStream(String videoUrl) throws IOException {
        URL url = new URL(videoUrl);
        return url.openConnection().getInputStream();
    }

    private static String extractAndUploadCover(FFmpegFrameGrabber ff, Alioss alioss, String position) throws IOException {
        int ffLength = ff.getLengthInFrames();
        Frame f;
        int i = 0;
        while (i < ffLength) {
            f = ff.grabFrame();
            if (f.image!= null) {
                Java2DFrameConverter converter = new Java2DFrameConverter();
                BufferedImage bi = converter.getBufferedImage(f);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ImageIO.write(bi, "png", byteArrayOutputStream);
                byte[] imageBytes = byteArrayOutputStream.toByteArray();
                String fileName = UUID.randomUUID() + ".png";
                String objectKey = position + fileName;
                OSS ossClient = createOSSClient(alioss);
                try {
                    uploadToOSS(ossClient, alioss, imageBytes, objectKey);
                    return getOSSObjectUrl(alioss, ossClient, objectKey);
                } finally {
                    ossClient.shutdown();
                }
            }
            i++;
        }
        return null;
    }

    private static OSS createOSSClient(Alioss alioss) {
        return new OSSClientBuilder().build(alioss.getRegion(), alioss.getAccesskeyid(), alioss.getAccesskeysecret());
    }

    private static void uploadToOSS(OSS ossClient, Alioss alioss, byte[] imageBytes, String objectKey) {
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType("image/png");
        ossClient.putObject(alioss.getBucket(), objectKey, new ByteArrayInputStream(imageBytes), metadata);
    }

    private static String getOSSObjectUrl(Alioss alioss, OSS ossClient, String objectKey) {
        return ossClient.generatePresignedUrl(alioss.getBucket(), objectKey, null).toString();
    }
}